/** JXR FILTER FOR HDF5
 ** this file contains the filter interface
 ** 
 **/

#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <H5PLextern.h>

#include <h5jxr_encode.c>
#include <h5jxr_decode.c>

//define available filter number (will be assigned by hdf5 group after registering the filter)
#define H5Z_FILTER_JXR 307
#define MINIMUM_JXR_SIZE_IN_BYTES 1000

static size_t H5Z_filter_jxr(unsigned int flags, size_t cd_nelmts,
                     const unsigned int cd_values[], size_t nbytes,
                     size_t *buf_size, void **buf);

// the following is dependent on hdf5 and therefore commented out for first tests
const H5Z_class2_t H5Z_JXR[1] = {{
    H5Z_CLASS_T_VERS,                       // H5Z_class_t version
    (H5Z_filter_t)H5Z_FILTER_JXR,           // Filter id number             
    1,                                      // encoder_present flag (set to true) 
    1,                                      // decoder_present flag (set to true) 
    "HDF5 jxr filter; see http://www.hdfgroup.org/services/contributions.html", 
                                            // Filter name for debugging    
    NULL,                                   // The "can apply" callback     
    NULL,                                   // The "set local" callback     
    (H5Z_func_t)H5Z_filter_jxr,             // The actual filter function   
}}; 

H5PL_type_t   H5PLget_plugin_type(void) {return H5PL_TYPE_FILTER;}
const void *H5PLget_plugin_info(void) {return H5Z_JXR;}

static size_t H5Z_filter_jxr(unsigned int flags, size_t cd_nelmts,
                     const unsigned int cd_values[], size_t nbytes,
                     size_t *buf_size, void **buf)
{
  // the height and width of the image to be filtered
  // is contained in the meta data and can be passed
  // to this filter function as entries of the array cd_value
  U16 height = cd_values[0];
  U16 width  = cd_values[1];
  U8 quality  = (U8) cd_values[2]; // quality 0...256

  printf("\n\n\n running filter:\n\t\tpbuf before: %d\n",*buf);
  printf("\t\theight width: %d %d\n",height,width);
  printf("\t\tsize of buffer: %d \n",sizeof(*buf));
  printf("\t\tencoding quality: %d\n",(U8) quality);
  printf("\t\tnbytes: %d\n",nbytes);
  printf("\t\tbuf[10] before: %d\n",((U16*)*buf)[10]);
  printf("\t\tbufsize before: %d\n",((U16*)*buf_size));

  size_t outbuflen;
  if (2*width*height>MINIMUM_JXR_SIZE_IN_BYTES)
      outbuflen = 2*width*height;
  else
      outbuflen = MINIMUM_JXR_SIZE_IN_BYTES;

  printf("\t\toutbuflen: %d\n",outbuflen);

  size_t outdatalen = 1;
  U16 *outbuf;
  outbuf = malloc(outbuflen);
  *buf_size = nbytes;

  if (flags) {
  //if (flags & H5Z_FLAG_REVERSE) {
  //if (flags) {

    /** Decompress data.
     **
     **/
    printf("decoding...\n");
    jxr_decode(buf,buf_size,outbuf,&outdatalen);//,outbuf_size,&outbuf);

  } else {

    /** Compress data.
     **
     **/
    printf("encoding...\n");
    jxr_encode(height,width,quality,buf,buf_size,outbuf,&outdatalen);//,outbuf_size,&outbuf);
    }

  /* Always replace the input buffer with the output buffer. */

	free(*buf); //segfault
	*buf = outbuf;
	*buf_size = outbuflen;

    printf("\n\t\tpbuf after: %d\n",(U16*)*buf);
	printf("\t\tbuf[10] after: %d\n",((U16*)*buf)[10]);
    printf("\t\tbufsize after: %d\n",outdatalen);
  return outdatalen;

 cleanupAndFail:
	//printf("failing and cleaning up: nothing to be done");
  return 0;
}
